{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**问题：**\n",
    "假设你正在为一个电影推荐系统设计一个简单的KNN算法。我们有以下一些用户的电影评分数据，数据由两个特征组成：用户对电影A和电影B的评分，分别在1-5之间。用户的标签（电影类型偏好）是动作片（标签0）或者是喜剧片（标签1）。我们有一个新用户，他给电影A评分为3，电影B评分为4。请问这个用户可能偏好哪种类型的电影？\n",
    "\n",
    "**数据：**\n",
    "\n",
    "| 用户   | 电影A评分 | 电影B评分 | 偏好类型 |\n",
    "| ------ | --------- | --------- | -------- |\n",
    "| 用户1  | 5         | 1         | 动作片   |\n",
    "| 用户2  | 4         | 2         | 动作片   |\n",
    "| 用户3  | 2         | 5         | 喜剧片   |\n",
    "| 用户4  | 1         | 4         | 喜剧片   |\n",
    "| 用户5  | 3         | 2         | 动作片   |\n",
    "| 用户6  | 2         | 5         | 喜剧片   |\n",
    "\n",
    "你需要做以下步骤：\n",
    "1. 构造数据\n",
    "2. 创建KNN模型\n",
    "3. 使用数据训练模型\n",
    "4. 预测新用户的喜好"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 0. 引入核心包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.neighbors import KNeighborsClassifier"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. X, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = np.array([\n",
    "    [5, 1],\n",
    "    [4, 2],\n",
    "    [2, 5],\n",
    "    [1, 4],\n",
    "    [3, 2],\n",
    "    [2, 5]\n",
    "])\n",
    "\n",
    "y = np.array([0, 0, 1, 1, 0, 1])  # 0表示动作片，1表示喜剧片"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. 创建 KNN 模型\n",
    "k = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "knn = KNeighborsClassifier(n_neighbors=1)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: black;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-1 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-1 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: block;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-1 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-1 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 1ex;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-1 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>KNeighborsClassifier(n_neighbors=1)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;KNeighborsClassifier<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.neighbors.KNeighborsClassifier.html\">?<span>Documentation for KNeighborsClassifier</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>KNeighborsClassifier(n_neighbors=1)</pre></div> </div></div></div></div>"
      ],
      "text/plain": [
       "KNeighborsClassifier(n_neighbors=1)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn.fit(X, y)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. 用模型推理(预测)用户的喜好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_user = np.array([[3, 4]])\n",
    "prediction = knn.predict(new_user)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5. 数据可视化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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kJiYiK+//rra4y82fDiwdav8LrGSd+e6usoLoOHD9RYakWkoLPz3LrCSEyeLzwAVFuonLiKq8fR+d1hZ0tLSlCYV9+zZE9HR0ZgzZw4+/PBDtGzZEjt27ChVTFW34cOBgAAgPh7IzgZ++61il8CISAvUPAwRQJmXwoiIalQRFBcXV+Z3AAgKCkJQUFD1BKQBc3Ogd29g1y75f1kAERER1Ww14onRRERERNWNRRARERGZJBZBREREZJJYBBEREZFJYhFEREREJolFEBEREZkkFkFERERkklgEERERkUliEUREREQmiUUQERERmSQWQURERGSSWAQRERGRSWIRRERERCaJRRARERGZJBZBREREZJJYBBEREZFJYhFEREREJolFEBEREZkkFkFERERkklgEERERkUliEUREREQmiUUQERERmSQWQURERGSSWAQRERGRSWIRRERERCaJRRARERGZJBZBREREZJJYBBEREZFJYhFEREREJslC0xVmzJihsl0ikcDa2hotWrRAQEAA6tWrV+XgiIiIiHRF4yIoKSkJp0+fRmFhIVq3bg0A+Pvvv2Fubg4PDw989dVXeO+995CQkIC2bdtqPWAiIiIibdD4clhAQAAGDBiA27dv49SpUzh16hRu3rwJPz8/BAcH49atW+jTpw/efffdcseKjIyEp6cnHBwc4ODgAG9vb+zevVtt/6ioKEgkEqWPtbW1pikQERERaX4maPHixYiNjYWDg4OirXbt2ggLC8PAgQMxbdo0fPzxxxg4cGC5Y7m6umLRokVo2bIlhBDYuHEjAgICkJSUhHbt2qlcx8HBARcvXlR8l0gkmqZAREREpHkRlJWVhbt375a61PXPP/8gOzsbAFCnTh08ffq03LFeeuklpe8LFixAZGQkjh8/rrYIkkgkcHZ21jRsIiIiIiUaF0EBAQGYNGkSli5dim7dugEATp48iffffx+BgYEAgD/++AOtWrXSaNzCwkJs2bIFjx8/hre3t9p+OTk5cHd3R1FRETp37oxPP/1UbcEEADKZDDKZTPG9uFDLz89Hfn6+RjGWp3g8bY9bUxh7foDx58j8DJ+x58j8DJ+uctTFPpMIIYQmK+Tk5ODdd9/Ft99+i4KCAgCAhYUFxo8fj4iICNSqVQvJyckAgE6dOpU7XkpKCry9vfHkyRPY2dkhOjoaQ4cOVdn32LFj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d97BzZs3Va6zbt06jBgxAu3bt1f6hISEIDMzE3v27NEo75YtW+K7777DhQsXcOLECYwZMwY2NjZKfZo2bYr9+/fjzp07lS5aPDw8MGDAALz22mv4448/kJSUhNdee03l2Ski0g0WQUSkloODAxwcHNQuX7RoEV555RW8+uqr6Ny5My5fvoy9e/eWmtcyZswYnDlzBi+//HKpgqIkW1tbxMfHo0mTJhg+fDjatGmDkJAQPHnyRGUcp06dwpkzZ/DKK6+UWla7dm30798f69at0yBjeVH14MEDdO7cGa+++qriEQAlLV26FLGxsXBzcyv12ABNfPvtt2jYsCH69OmDl19+GVOmTIG9vT2sra0rPSYRVZxECCH0HQQREQE3b96Em5sb9u3bh/79++s7HCKjxyKIiEhPDhw4gJycHHTo0AHp6emYOXMmbt26hb///rvUpGoi0j7eHUZEpCf5+fn48MMPceXKFdjb26Nnz57YtGkTCyCiasIzQURERGSSODGaiIiITBKLICIiIjJJLIKIiIjIJLEIIiIiIpPEIoiIiIhMEosgIiIiMkksgoiIiMgksQgiIiIik8QiiIiIiEzS/wHpBwyBZUGZmgAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.title(\"User Movie Preference\", size=15) \n",
    "plt.xlabel(\"Movie A rating\")\n",
    "plt.ylabel(\"Movie B rating\")\n",
    "plt.grid()\n",
    "\n",
    "# 绘制原始样本点，要求不同的影片喜好类别用不同的颜色标记\n",
    "# 提示: 用scatter散点图绘制，用它的参数c实现不同的类别用不同的颜色标记\n",
    "pt_colors = ['b', 'g', 'y']\n",
    "for i, x in enumerate(X):\n",
    "    plt.scatter(x[0], x[1], c=pt_colors[i % len(pt_colors)])\n",
    "    plt.text(x[0], x[1], f'({x[0]},{x[1]})')\n",
    "    \n",
    "    \n",
    "# 绘制新数据点，用红色x标记，大小为8\n",
    "# 提示：用plt.plot()绘制，用它的参数marker实现不同的标记符号\n",
    "for i, pt in enumerate(new_user):\n",
    "    plt.text(pt[0], pt[1], f'  ({pt[0]},{pt[1]})') \n",
    "# 新数据最近邻索引为第一个最近邻的索引\n",
    "dist, idx = knn.kneighbors(new_user)\n",
    "nearest = idx[0] # 获取最近邻点的坐标，这是一个列表，第一个元素是x坐标，第二个元素是y坐标\n",
    "\n",
    "# 用红线标记新数据点与最近邻点的连接线\n",
    "# 提示：用plt.plot()绘制，用 r-- 实现红色虚线\n",
    "for i, pt in enumerate(new_user):\n",
    "    plt.plot(pt[0], pt[1], 'x', c='red')\n",
    "    plt.text(pt[0], pt[1], f'  ({pt[0]},{pt[1]})')\n",
    "    NN = X[idx[i][0]]\n",
    "    plt.plot([pt[0], NN[0]], [pt[1], NN[1]], 'r--')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
